﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using StreetlightGames.SpaceShooter.Patterns;
using System.Reflection;
using System.IO;
using Microsoft.Xna.Framework;
using System.Xml;
using StreetlightGames.XnaEngine;

namespace StreetlightGames.SpaceShooter
{
    [DataContract]
    public class WaveData
    {
        /// <summary>Gets or sets the Name value</summary>
        [DataMember]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private string _name;
        
        /// <summary>Gets or sets the Ships value</summary>
        [DataMember]
        public List<ShipData> Ships
        {
            get
            {
                if (_ships == null)
                {
                    _ships = new List<ShipData>();
                }
                return _ships;
            }
            set { _ships = value; }
        }
        private List<ShipData> _ships;
        
        public WaveData()
        {
        }

        public static WaveData CreateDefault()
        {
            WaveData waveData = new WaveData();
            string beeName = typeof(BeeShip).Name;
            string butterflyName = typeof(ButterflyShip).Name;
            string motherShipName = typeof(MotherShip).Name;
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = beeName;
                waveData.Ships.Add(ship);
            }
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = butterflyName;
                waveData.Ships.Add(ship);
            }
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = motherShipName;
                waveData.Ships.Add(ship);
            }
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = butterflyName;
                waveData.Ships.Add(ship);
            }
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = butterflyName;
                waveData.Ships.Add(ship);
            }
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = beeName;
                waveData.Ships.Add(ship);
            }
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = beeName;
                waveData.Ships.Add(ship);
            }
            float rad = 300f;
            float shipSpeed = 1000;
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = waveData.Ships[i];
                ship.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(200, 0, -1500));
                ship.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
                ship.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4));
                ship.AddPattern(new ContinueForward(500f));
                ship.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4 + MathHelper.Pi));
                ship.StartDelay = string.Format("{0:0.0}", 0.2f * (float)i);
                ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-50 + i % 2 * 100, 0, -1000 + 100 * (int)(i / 2)));
                ship.AddPattern(new MoveToFormation());
                ship.AddPattern(new Hover());
            }
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = waveData.Ships[i + 4];
                ship.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-200, 0, -1500));
                ship.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
                ship.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4));
                ship.AddPattern(new ContinueForward(500f));
                ship.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4 + MathHelper.Pi));
                ship.StartDelay = string.Format("{0:0.0}", 0.2f * (float)i);
                ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-50 + i % 2 * 100, 0, -1200 + 100 * (int)(i / 2)));
                ship.AddPattern(new MoveToFormation());
                ship.AddPattern(new Hover());
            }
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = waveData.Ships[i + 8];
                ship.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-800, 0, -200));
                ship.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(shipSpeed, 0, 0));
                ship.AddPattern(new ContinueForward(400f));
                ship.AddPattern(new FlyInCircle(rad, 1, MathHelper.TwoPi + MathHelper.PiOver2));
                ship.AddPattern(new MoveToFormation());
                ship.AddPattern(new Hover());
                ship.StartDelay = string.Format("{0:0.0}", 3f + (float)i * 2f * 0.2f);
                ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-150 + 100 * i, 0, -1300));
            }
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = waveData.Ships[i + 12];
                ship.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-800, 0, -200));
                ship.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(shipSpeed, 0, 0));
                ship.AddPattern(new ContinueForward(400f));
                ship.AddPattern(new FlyInCircle(rad, 1, MathHelper.TwoPi + MathHelper.PiOver2));
                ship.AddPattern(new MoveToFormation());
                ship.AddPattern(new Hover());
                ship.StartDelay = string.Format("{0:0.0}", 3.2f + (float)i * 2f * 0.2f);
                ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-150 + i % 2 * 300, 0, -1200 + 100 * (int)(i / 2)));
            }
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = waveData.Ships[i + 16];
                ship.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(800, 0, -200));
                ship.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(-shipSpeed, 0, 0));
                ship.AddPattern(new ContinueForward(400f));
                ship.AddPattern(new FlyInCircle(rad, -1, MathHelper.TwoPi + MathHelper.PiOver2));
                ship.AddPattern(new MoveToFormation());
                ship.AddPattern(new Hover());
                ship.StartDelay = string.Format("{0:0.0}", 8f + (float)i * 0.2f);
                if (i < 4)
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(250 + i % 2 * 100, 0, -1200 + 100 * (int)(i / 2)));
                }
                else
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-350 + i % 2 * 100, 0, -1200 + 100 * (int)((i - 4) / 2)));
                }
            }
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = waveData.Ships[i + 24];
                ship.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(200, 0, -1500));
                ship.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
                ship.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4));
                ship.AddPattern(new ContinueForward(500f));
                ship.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4 + MathHelper.Pi));
                ship.StartDelay = string.Format("{0:0.0}", 12 + 0.2f * (float)i);
                if (i < 4)
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(150 + i % 2 * 100, 0, -1000 + 100 * (int)(i / 2)));
                }
                else
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-250 + i % 2 * 100, 0, -1000 + 100 * (int)((i - 4) / 2)));
                }
                ship.AddPattern(new MoveToFormation());
                ship.AddPattern(new Hover());
            }
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = waveData.Ships[i + 32];
                ship.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-200, 0, -1500));
                ship.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
                ship.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4));
                ship.AddPattern(new ContinueForward(500f));
                ship.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4 + MathHelper.Pi));
                ship.StartDelay = string.Format("{0:0.0}", 17 + 0.2f * (float)i);
                if (i < 4)
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-450 + i % 2 * 100, 0, -1000 + 100 * (int)(i / 2)));
                }
                else
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(350 + i % 2 * 100, 0, -1000 + 100 * (int)((i - 4) / 2)));
                }
                ship.AddPattern(new MoveToFormation());
                ship.AddPattern(new Hover());
            }
            return waveData;
        }

        public WaveData Duplicate()
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(WaveData));
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            XmlWriter xw = new XmlTextWriter(sw);
            serializer.WriteObject(xw, this);
            StringReader sr = new StringReader(sb.ToString());
            XmlReader xr = new XmlTextReader(sr);
            WaveData waveData = serializer.ReadObject(xr) as WaveData;
            waveData.Name = "Copy of " + Name;
            return waveData;
        }
    }
}
